package cn.ibizlab.util.domain;

import cn.hutool.core.bean.DynaBean;
import cn.ibizlab.util.helper.BeanCache;
import cn.ibizlab.util.helper.CachedBeanCopier;
import com.alibaba.fastjson.annotation.JSONField;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.data.annotation.Transient;
import org.springframework.util.AlternativeJdkIdGenerator;
import org.springframework.util.ObjectUtils;
import java.io.Serializable;
import java.util.*;

public class EntityBase implements IEntity,Serializable {

    @JsonIgnore
    @JSONField(serialize = false)
    @TableField(exist = false)
    @Transient
    private Set<String> focusNull;

    @JsonIgnore
    @JSONField(serialize = false)
    @Transient
    @Override
    public Set<String> getFocusNull() {
        if(focusNull==null) {
            focusNull=new HashSet<>();
        }
        return focusNull;
    }

    public void setFocusNull(Set<String> focusNull) {
        this.focusNull = focusNull;
    }

    public void modify(String field,Object val) {
        if(val==null) {
            this.getFocusNull().add(field.toLowerCase());
        }
        else {
            this.getFocusNull().remove(field.toLowerCase());
        }
    }

    public Serializable getDefaultKey(boolean gen) {
        String Id=(new AlternativeJdkIdGenerator()).generateId().toString();
        return gen?Id.replace("-", ""):Id;
    }


    @JsonIgnore
    @JSONField(serialize = false)
    @Transient
    public Serializable getContextParentKey() {
        return (Serializable)get("srfparentkey");
    }

    @JsonIgnore
    @JSONField(serialize = false)
    @Transient
    public String getContextParentEntity(){
        Object parentEntity;
        return (parentEntity = get("srfparentdename"))==null?"":parentEntity.toString();
    }

    @JsonIgnore
    @JSONField(serialize = false)
    @TableField(exist = false)
    @Transient
    private DynaBean map;

    @JsonIgnore
    @JSONField(serialize = false)
    @Transient
    private DynaBean getMap()
    {
        if(map==null) {
           map=DynaBean.create(this);
        }
        return  map;
    }

    @JsonIgnore
    @TableField(exist = false)
    @JSONField(serialize = false)
    @Transient
    private Context ctx;

    @JsonIgnore
    @JSONField(serialize = false)
    public Context getCtx() {
        if(ctx == null)
            ctx = new Context();
        return ctx;
    }

    @JsonIgnore
    @TableField(exist = false)
    @JSONField(serialize = false)
    @Transient
    private Map<String,Object> extensionparams=new HashMap<String,Object>();

    @JsonIgnore
    @JSONField(serialize = false)
    @Transient
    @Override
    public Map<String, Object> getExtensionparams() {
        return extensionparams;
    }

    public void setExtensionparams(Map<String, Object> extensionparams) {
        this.extensionparams = extensionparams;
    }

    public Object get(String field) {
        String fieldRealName= BeanCache.getFieldRealName(this.getClass(),field);
        if(!ObjectUtils.isEmpty(fieldRealName)) {
            return getMap().get(fieldRealName);
        }
        else {
            return this.extensionparams.get(field.toLowerCase());
        }
    }

    @JsonAnyGetter
    @JSONField(name = "_any", unwrapped = true, serialize = true, deserialize = false)
    public Map<String , Object> any() {
        return extensionparams;
    }

    @JsonAnySetter
    @JSONField(name = "_any", unwrapped = true, serialize = false, deserialize = true)
    public void set(String field, Object value) {
        field=field.toLowerCase();
        String fieldRealName=BeanCache.getFieldRealName(this.getClass(),field);
        if(!ObjectUtils.isEmpty(fieldRealName)) {
            if (value == null) {
                getMap().set(fieldRealName, null);
            }
            else {

                getMap().set(fieldRealName, BeanCache.fieldValueOf(this.getClass(), fieldRealName, value));
            }
        }
        else {
            this.extensionparams.put(field.toLowerCase(),value);
        }
    }


    /**
     * 复制当前对象数据到目标对象
     * @param targetEntity 目标数据对象
     * @param includeEmpty  是否包括空值
     * @param <T>
     * @return
     */
    public <T> T copyTo(T targetEntity, boolean includeEmpty){
        CachedBeanCopier.copy(this,targetEntity,includeEmpty);
        return targetEntity;
    }

    /**
     * 复制当前对象数据到目标对象，粘贴重置
     * @param targetEntity 目标数据对象
     * @param includeEmpty  是否包括空值
     * @param <T>
     * @return
     */
    public <T> T pasteTo(T targetEntity, boolean includeEmpty){
        return copyTo(targetEntity,includeEmpty);
    }

    /**
    * 重置当前数据对象属性值
    * @param field
    */
    @Override
    public void reset(String field){
        this.getFocusNull().remove(field.toLowerCase());
    }

}